A Pythonic Card Deck


In [6]:
import collections

Card = collections.namedtuple('Card', ['rank', 'suit'])

class FrenchDeck:
    ranks = [str(n) for n in list(range(2, 11)) + list('JQKA')]
    suits = 'spades diamonds clubs hearts'.split()

    def __init__(self):
        self._cards = [Card(rank, suit) for suit in self.suits
                      for rank in self.ranks]

    def __len__(self):
        return len(self._cards)

    def __getitem__(self, position):
        return self._cards[position]

In [46]:
deck = FrenchDeck()

In [8]:
len(deck)


Out[8]:
52

In [9]:
deck[17]


Out[9]:
Card(rank='6', suit='diamonds')

In [10]:
from random import choice

In [14]:
choice([3,4,6,7,8])  # picks 1 from a list


Out[14]:
3

In [35]:
choice(deck)


Out[35]:
Card(rank='4', suit='spades')

In [37]:
choice(deck)


Out[37]:
Card(rank='K', suit='hearts')

In [63]:
deck[:12]


Out[63]:
[Card(rank='2', suit='spades'),
 Card(rank='3', suit='spades'),
 Card(rank='4', suit='spades'),
 Card(rank='5', suit='spades'),
 Card(rank='6', suit='spades'),
 Card(rank='7', suit='spades'),
 Card(rank='8', suit='spades'),
 Card(rank='9', suit='spades'),
 Card(rank='10', suit='spades'),
 Card(rank='J', suit='spades'),
 Card(rank='Q', suit='spades'),
 Card(rank='K', suit='spades')]

In [41]:
for count, card in enumerate(deck):
    print(card)
    if count > 6:
        break


Card(rank='2', suit='spades')
Card(rank='3', suit='spades')
Card(rank='4', suit='spades')
Card(rank='5', suit='spades')
Card(rank='6', suit='spades')
Card(rank='7', suit='spades')
Card(rank='8', suit='spades')
Card(rank='9', suit='spades')

In [43]:
for count, card in enumerate(reversed(deck)):
    print(card)
    if count > 6:
        break


Card(rank='A', suit='hearts')
Card(rank='K', suit='hearts')
Card(rank='Q', suit='hearts')
Card(rank='J', suit='hearts')
Card(rank='10', suit='hearts')
Card(rank='9', suit='hearts')
Card(rank='8', suit='hearts')
Card(rank='7', suit='hearts')

In [47]:
Card('Q', 'hearts') in deck


Out[47]:
True

In [49]:
Card('Q', 'dogs') in deck


Out[49]:
False

In [67]:
# sorting

suit_values = dict(spades=3, hearts=2, diamonds=1, clubs=0)

def spades_high(card):
    rank_value = FrenchDeck.ranks.index(card.rank)
    return rank_value * len(suit_values) + suit_values[card.suit]

In [68]:
for card in sorted(deck, key=spades_high):
    print(card)


Card(rank='2', suit='clubs')
Card(rank='2', suit='diamonds')
Card(rank='2', suit='hearts')
Card(rank='2', suit='spades')
Card(rank='3', suit='clubs')
Card(rank='3', suit='diamonds')
Card(rank='3', suit='hearts')
Card(rank='3', suit='spades')
Card(rank='4', suit='clubs')
Card(rank='4', suit='diamonds')
Card(rank='4', suit='hearts')
Card(rank='4', suit='spades')
Card(rank='5', suit='clubs')
Card(rank='5', suit='diamonds')
Card(rank='5', suit='hearts')
Card(rank='5', suit='spades')
Card(rank='6', suit='clubs')
Card(rank='6', suit='diamonds')
Card(rank='6', suit='hearts')
Card(rank='6', suit='spades')
Card(rank='7', suit='clubs')
Card(rank='7', suit='diamonds')
Card(rank='7', suit='hearts')
Card(rank='7', suit='spades')
Card(rank='8', suit='clubs')
Card(rank='8', suit='diamonds')
Card(rank='8', suit='hearts')
Card(rank='8', suit='spades')
Card(rank='9', suit='clubs')
Card(rank='9', suit='diamonds')
Card(rank='9', suit='hearts')
Card(rank='9', suit='spades')
Card(rank='10', suit='clubs')
Card(rank='10', suit='diamonds')
Card(rank='10', suit='hearts')
Card(rank='10', suit='spades')
Card(rank='J', suit='clubs')
Card(rank='J', suit='diamonds')
Card(rank='J', suit='hearts')
Card(rank='J', suit='spades')
Card(rank='Q', suit='clubs')
Card(rank='Q', suit='diamonds')
Card(rank='Q', suit='hearts')
Card(rank='Q', suit='spades')
Card(rank='K', suit='clubs')
Card(rank='K', suit='diamonds')
Card(rank='K', suit='hearts')
Card(rank='K', suit='spades')
Card(rank='A', suit='clubs')
Card(rank='A', suit='diamonds')
Card(rank='A', suit='hearts')
Card(rank='A', suit='spades')

How Special Methods Are Used


In [69]:
from math import hypot

class Vector:

    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    def __repr__(self):
        return 'Vector(%r, %r)' % (self.x, self.y)

    def __abs__(self):
        return hypot(self.x, self.y)

    def __bool__(self):
        return bool(abs(self))

    def __add__(self, other):
        x = self.x + other.x
        y = self.y + other.y
        return Vector(x, y)

    def __mul__(self, scalar):
        return Vector(self.x * scalar, self.y * scalar)

In [81]:
Vector(4,5) + Vector(1,2)


Out[81]:
Vector(5, 7)

In [82]:
Vector(1,2) * 3


Out[82]:
Vector(3, 6)

In [77]:
bool(Vector(4,5))


Out[77]:
True

In [83]:
repr(Vector(1,2))


Out[83]:
'Vector(1, 2)'

In [84]:
str(Vector(1,2))


Out[84]:
'Vector(1, 2)'